home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / net / netware / nwsema.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-03-20  |  13.6 KB  |  392 lines

  1. {$X+,V-,B-}
  2. Unit nwSema;
  3.  
  4. INTERFACE
  5.  
  6. { Primary functions:                    Interrupt: comments:
  7.  
  8. * OpenSemaphore                         (F220/00)
  9. * ExamineSemaphore                      (F220/01)
  10. * WaitOnSemaphore                       (F220/02)
  11. * SignalSemaphore                       (F220/03)
  12. * CloseSemaphore                        (F220/04)
  13.   GetSemaphoreInformation               (F217/F3)
  14.  
  15. Notes: -Functions marked with a '*' are tested and found correct.
  16.  
  17. }
  18.  
  19. Uses nwMisc;
  20.  
  21. Var Result:word;
  22.  
  23. {C500 [2.0/2.1/3.x]}
  24. FUNCTION OpenSemaphore( SemName :String; InitVal :Integer;
  25.                         VAR SemHandle :LongInt;
  26.                         VAR OpenCount :Word               ) :Boolean;
  27. { Semaphores are used for exclusion when record locking is not appropriate }
  28. { The value is set the first time the semaphore is opened, thereafter you }
  29. { must use wait semaphore or signal semaphore to change the value }
  30.  
  31. {C501 [2.0/2.1/3.x]}
  32. FUNCTION ExamineSemaphore( SemHandle :LongInt;
  33.                            VAR Value     :Integer;
  34.                            VAR OpenCount :Word     ) :Boolean;
  35. { This functions returns the current value and open count of a semaphore.}
  36. { The semaphore value is decremented for each WAIT_ON_SEMAPHORE, }
  37. {   and incremented for each SIGNAL_SEMAPHORE.  A negative semaphore }
  38. {   value indicates the number of processes waiting to use the semaphore. }
  39. { Count is the number of processes that are using the same semaphore.}
  40. {   The open count is incremented any time a station opens the semaphore }
  41. {   This can be used for controlling the number of users using your software }
  42. { Value is the current value associates with the semaphore. }
  43.  
  44. {C502 [2.0/2.1/3.x]}
  45. FUNCTION WaitOnSemaphore( SemHandle :LongInt;
  46.                           Wait_Time :Word  ) :Boolean;
  47. { Decrement the semaphore value and, if it is negative,           }
  48. { wait until it becomes non-negative or until a }
  49. { timeout occurs. }
  50.  
  51. {C503 [2.0/2.1/3.x]}
  52. FUNCTION SignalSemaphore(SemHandle:LongInt) : Boolean;
  53. { Increment the semaphore value and release if waiting. If any stations }
  54. { are waiting, the station that has been waiting the longest will be }
  55. { signalled to proceed }
  56.  
  57. {C504 [2.0/2.1/3.x]}
  58. FUNCTION CloseSemaphore(SemHandle:LongInt) : Boolean;
  59. { Decrement the open count of a semaphore.}
  60. {  When the open count goes to zero, the semaphore is destroyed. }
  61. { In other words: if the requesting process is the last process to have
  62.   this semaphore open, the semaphore is deleted.}
  63.  
  64.  
  65. IMPLEMENTATION {=============================================================}
  66.  
  67. uses dos;
  68.  
  69. {F:C500 [2.x/3.x]}
  70. FUNCTION OpenSemaphore(SemName : String; InitVal : Integer;
  71.                         VAR SemHandle : LongInt;
  72.                         VAR OpenCount : Word)             : Boolean;
  73. Var Regs:Registers;
  74. BEGIN
  75. WITH Regs
  76. DO BEGIN
  77.    IF (InitVal < 0) OR (InitVal > 127)
  78.     THEN BEGIN
  79.          Result:=$FF;                          { Invalid Semaphore Value }
  80.          OpenSemaphore := False;    { InitVal must be between 0 and 127 }
  81.          Exit;
  82.          END;
  83.    IF (SemName[0]>#127)                { Semaphore must not exceed 127 chars }
  84.     THEN BEGIN
  85.          Result:=$FE;                    { Invalid Semaphore name Length }
  86.          OpenSemaphore := false;
  87.          Exit;
  88.          END;
  89.     AH := $C5;                                      { Semaphore function }
  90.     AL := $00;                                   { Sub-Function 0 = open }
  91.     DS := Seg(SemName);                           { DS:DX points to name }
  92.     DX := Ofs(SemName);                         { Byte 0 = length 0..127 }
  93.     CL := InitVal;                                { Initial Value 0..127 }
  94.  
  95.     MsDos(Regs);                                    { Give it to Int 21h }
  96.  
  97.     OpenCount := BL;              { Number of users using this semaphore }
  98.     Result:=AL;
  99.     OpenSemaphore := (AL = 0);                { OK if AL comes back as 0 }
  100.                                       { FEh Invalid Semaphore Name Length}
  101.                                       { FFh Invalid Semaphore Value      }
  102.     SemHandle:=MakeLong(CX,DX);       { CX:DX holds the semaphore handle }
  103.   END;                                                    { with Regs do }
  104. END;                                            {Function Open_Semaphore }
  105.  
  106.  
  107. {F:C501 [2.x/3.x]}
  108. FUNCTION ExamineSemaphore(SemHandle:LongInt;
  109.                            VAR Value     : Integer;
  110.                            VAR OpenCount : Word  )  : Boolean;
  111. { The semaphore value that comes back in CL is the count from the open call }
  112. { DL represents the current open count - the open count is incremented }
  113. { anytime  a station opens the semaphore this can be used for controlling }
  114. { the number of users using your software }
  115. Var Regs:Registers;
  116. BEGIN
  117. WITH Regs
  118.  DO BEGIN
  119.     AH := $C5;                                 { Semaphore function call }
  120.     AL := 1;                                  { Sub-Function 1 = examine }
  121.     CX := HiLong(SemHandle);
  122.     DX := LowLong(SemHandle);
  123.  
  124.     MsDos(Regs);                                        { Give it to DOS }
  125.  
  126.     Value := CX;                                 { Semaphore value in CX }
  127.     OpenCount := DL;                       { Number using this semaphore }
  128.     Result := AL;                              { AL = $FF invalid handle }
  129.     ExamineSemaphore := (AL = 0);                     { AL = 0 means OK }
  130.     END;
  131. END;                                        { function Examine_Semaphore }
  132.  
  133. {F:C502 [2.x/3.x]}
  134. FUNCTION WaitOnSemaphore( SemHandle : LongInt;
  135.                             Wait_Time : Word  ) : Boolean;
  136. { Decrement the semaphore value and wait if it is negative.  If negative,}
  137. { the workstation will wait until it becomes non-negative or until a }
  138. { timeout occurs. }
  139. Var regs:registers;
  140. BEGIN
  141. WITH Regs
  142. DO BEGIN
  143.    AH := $C5;                                 { Semaphore function call }
  144.    AL := 2;                                     { Sub-Function 2 = wait }
  145.    BP := Wait_Time;                      { In 1/18 seconds, 0 = No wait }
  146.    CX := HiLong(SemHandle);
  147.    DX := LowLong(SemHandle);
  148.  
  149.    MsDos(Regs);                                        { Give it to DOS }
  150.  
  151.    Result:=AL;
  152.    WaitOnSemaphore := (AL = 0);             { AL = $00 means OK,
  153.                                                      $FE timeout failure,
  154.                                                      $FF Invalid handle }
  155.   END;
  156. END;                                          { function Wait_Semaphore }
  157.  
  158. {C503 [2.x/3.x]}
  159. FUNCTION SignalSemaphore(SemHandle:LongInt) : Boolean;
  160. { Increment the semaphore value and release if waiting.  If any stations}
  161. { are waiting, the station that has been waiting the longest will be    }
  162. { signalled to proceed }
  163. Var Regs:Registers;
  164. BEGIN
  165. WITH Regs
  166. DO BEGIN
  167.     AH := $C5;                                 { Semaphore function call }
  168.     AL := 3;                                   { Sub-Function 3 = signal }
  169.     CX := HiLong(SemHandle);
  170.     DX := LowLong(SemHandle);
  171.  
  172.     MsDos(Regs);                                        { Give it to DOS }
  173.  
  174.     Result:=AL;
  175.     SignalSemaphore := (AL = 0); { AL = $00 means OK, else
  176.                                          $01 overflow ( value > 127 ) or
  177.                                          $FF Invalid handle }
  178.   END;
  179. END;                                         { function Signal_Semaphore }
  180.  
  181. {C504 [2.x/3.x]}
  182. FUNCTION CloseSemaphore(SemHandle:LongInt) : Boolean;
  183. { Decrement the open count of a semaphore.  When the open count goes     }
  184. { to zero, the semaphore is destroyed.                                   }
  185. Var Regs:Registers;
  186. BEGIN
  187. WITH Regs
  188. DO BEGIN
  189.     AH := $C5;                                  { Semaphore function call }
  190.     AL := 04;                                    { Sub-Function 4 = close }
  191.     CX := HiLong(SemHandle);
  192.     DX := LowLong(SemHandle);
  193.  
  194.     MsDos(Regs);                                          { Give it to DOS }
  195.  
  196.     Result:=AL;
  197.     CloseSemaphore := (AL = 0);     { AL = 0 means OK, FF: Invalid handle  }
  198.   END;
  199. END;                                            { function Close_Semaphore }
  200.  
  201.  
  202.  
  203. {E3E1 [2.1x/2.2]
  204. GET CONNECTION'S SEMAPHORES
  205.     AH = E3h subfn E1h
  206.     DS:SI -> request buffer (see below)
  207.     ES:DI -> reply buffer (see below)
  208. Return: AL = status
  209.         00h successful
  210.         C6h no console rights
  211. Notes:    this function is supported by Advanced NetWare 2.1+
  212.     the calling workstation must have console operator privileges
  213. SeeAlso: AH=E3h/SF=C8h,AH=E3h/SF=DBh,AH=E3h/SF=DFh,AH=E3h/SF=E2h
  214.  
  215. Format of request buffer:
  216. Offset    Size    Description
  217.  00h    WORD    0005h (length of following data)
  218.  02h    BYTE    E1h (subfunction "Get Connection's Semaphores")
  219.  03h    WORD    (big-endian) logical connection number
  220.  05h    WORD    (big-endian) last record seen (0000h on first call)
  221.  
  222. Format of reply buffer:
  223. Offset    Size    Description
  224.  00h    WORD    (call) size of following results record (max 1FEh)
  225.  02h    WORD    next request record (place in "last record" field on next call)
  226.  04h    BYTE    number of records following
  227.  05h    var    array of Semaphore Information Records
  228.  
  229. Format of Semaphore Information Record:
  230. Offset    Size    Description
  231.  00h    WORD    (big-endian) open count
  232.  02h    BYTE    semaphore value (-128 to 127)
  233.  03h    BYTE    task number
  234.  04h    BYTE    lock type
  235.  05h    BYTE    length of semaphore's name
  236.  06h  N BYTEs    semaphore's name
  237.      14 BYTEs    filename}
  238.  
  239.  
  240. {E3E2 [2.1x/2.2]
  241. GET SEMAPHORE INFORMATION
  242.     AH = E3h subfn E2h
  243.     DS:SI -> request buffer (see below)
  244.     ES:DI -> reply buffer (see below)
  245. Return: AL = status
  246.         00h successful
  247.         C6h no console rights
  248. Notes:    this function is supported by Advanced NetWare 2.1+
  249.     the calling workstation must have console operator privileges
  250. SeeAlso: AH=E3h/SF=C8h,AH=E3h/SF=E1h
  251.  
  252. Format of request buffer:
  253. Offset    Size    Description
  254.  00h    WORD    length of following data (max 83h)
  255.  02h    BYTE    E2h (subfunction "Get LAN Driver's Configuration Information")
  256.  03h    WORD    (big-endian) last record seen (0000h on first call)
  257.  05h    BYTE    length of semaphore's name (01h-7Fh)
  258.  06h  N BYTEs    semaphore's name
  259.  
  260. Format of reply buffer:
  261. Offset    Size    Description
  262.  00h    WORD    (call) size of following results buffer (max 1FEh)
  263.  02h    WORD    next request record (place in "last record" on next call)
  264.         0000h if no more
  265.  04h    WORD    (big-endian) number of logical connections opening semaphore
  266.  06h    BYTE    semaphore value (-127 to 128)
  267.  07h    BYTE    number of records following
  268.  08h    var    array of Semaphore Information records (see below)
  269.  
  270. Format of Semaphore Information:
  271. Offset    Size    Description
  272.  00h    WORD    (big-endian) logical connection number
  273.  02h    BYTE    task number}
  274.  
  275. {F217/F3 [3.11+]}
  276. Function GetSemaphoreInformation(SemaName:string;
  277.                             {i/o:} Var ReqRecordNbr:Integer;
  278.                             {out:} Var openCount:word;
  279.                                    Var semValue:byte;
  280.                                    Var connections:TconnectionList):boolean;
  281.  
  282. {   This call returns information about a single semaphore.  The
  283.     values returned are similiar to those returned in the old
  284.     version of this call.  This function may be called iteratively
  285.     to return all of the connection information for the specified
  286.     semaphore. }
  287. { 2.x: ?? if there are no more records, ReqRecordNbr is set to 0... }
  288. { need console rights to do this.. }
  289. { The function returns the connectionNumbers and taskNumbers as words.
  290.   for the sake of compatibilty, they are returned as bytes. Not too many
  291.   >250 user licences floating around.. I hope.. }
  292. Var req:record
  293.         len      :word; {lo-hi !}
  294.         subF     :byte;
  295.         lastRec  :word; {hi-lo, initially 0 }
  296.         _semaName:string; { max len=128 }
  297.         end;
  298.     reply:record
  299.           nextRec        :word; {hi-lo }
  300.           _OpenCount     :word; {hi-lo }
  301.           _semValue      :byte;
  302.                      { ?? Opencount:byte en semvalue:word ?? }
  303.           NumberOfRecords:word; {hi-lo }
  304.           _connTask:array[1..100] of record
  305.                                      connNbr,      {hi-lo !}
  306.                                      taskNbr:word; {hi-lo !}
  307.                                      end;
  308.           end;
  309.    regs:registers;
  310.    t:byte;
  311. BEGIN
  312. With req
  313.  do begin
  314.     subF:=$F3;
  315.     if ReqRecordNbr=-1
  316.      then lastRec:=0 { correct false initial value.}
  317.      else lastRec:=swap(ReqRecordNbr); {force hi-lo}
  318.     _semaName:=semaName; UpString(_semaName);
  319.     if semaName[0]>#127 then _semaName[0]:=#127;
  320.     len:=ord(semaName[0])+6;
  321.     end;
  322. With regs
  323.  do begin
  324.     ax := $f217;
  325.     ds:=SEG(req);   si := OFs(req);
  326.     cx:=sizeOf(req);
  327.     es:=SEG(reply); di := OFs(reply);
  328.     dx:=sizeOf(reply);
  329.     MsDos(regs);
  330.     result:=al;
  331.     end;
  332.  
  333. If result=0
  334.  then with reply
  335.        do begin
  336.           FillChar(connections,sizeOf(connections),#0);
  337.           for t:=0 to swap(NumberOfRecords) { <= 100, force lo-hi }
  338.            do begin
  339.               if _connTask[t].connNbr<=$FF
  340.                then connections[t]:=hi(_connTask[t].connNbr); {= LO}
  341.               end;
  342.           Opencount:=swap(_opencount); { force lo-hi }
  343.           ReqRecordNbr:=swap(nextRec); { force lo-hi }
  344.           semValue:=_semValue;
  345.           end;
  346.  
  347. GetSemaphoreInformation:=(result=0);
  348. end;
  349.  
  350.  
  351. {F2/ [2.15c+]
  352. Function    (  {i/o:}  {out: :boolean;
  353.  
  354. Var req:record
  355.         len      :word;
  356.         subF     :byte;
  357.  
  358.         end;
  359.     reply:record
  360.  
  361.           end;
  362.    regs:registers;
  363. BEGIN
  364. With req
  365.  do begin
  366.     subF:=
  367.  
  368.     len:=
  369.     end;
  370. With regs
  371.  do begin
  372.     ax := $f217;
  373.     ds:=SEG(req);   si := OFs(req);
  374.     cx:=sizeOf(req);
  375.     es:=SEG(reply); di := OFs(reply);
  376.     dx:=sizeOf(reply);
  377.     MsDos(regs);
  378.     result:=al;
  379.     end;
  380.  
  381. If result=0
  382.  then with reply
  383.        do begin
  384.  
  385.  
  386.           end;
  387.  
  388.     :=(result=0);
  389. end;}
  390.  
  391. BEGIN
  392. END.